import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from tkcalendar import DateEntry
from datetime import datetime
from dateutil import parser
from tabulate import tabulate
import pandas as pd
from tkinter import messagebox
class MainUi:
    def __init__(self, root):
        self.root = root

        self.callback = None

        self.filePath = tk.StringVar()
        self.mainTabName = tk.StringVar()
        self.dateTabName = tk.StringVar()
        self.patrolTabName = tk.StringVar()


        self.placeholdeMain = "例：晚托"
        self.placeholdePatrol = "例：行政巡堂"
        self.placeholdeDate = "例：调休补课"

        self.placeholdeMoreStart = "例：2025-01-01"
        self.placeholdeMoreEnd = "例：2025-01-10"


        self.mainTabName.set("")
        self.dateTabName.set("")
        self.patrolTabName.set("")


        self.dateRadioMoreFrame = None
        self.dateRadioOneFrame = None
        self.dateTypeSelected = tk.StringVar()
        self.dateTypeSelected.set("one")
        self.dateMoreStart = tk.StringVar()
        self.dateMoreEnd = tk.StringVar()
        
        self.dateMoreStart.set("")
        self.dateMoreEnd.set("")

        self.yearOneCombobox = None
        self.monthOneCombobox = None

        self.tree = None
        self.resultData = pd.DataFrame({})

        self.setup_ui()

    def getResutData(self):
        return self.df
    
    def getFilePath(self):
        return self.filePath
    
    def getFileTabMainName(self):
        return self.mainTabName
    
    def getFileTabDateTabName(self):
        return self.dateTabName
    
    def getFileTabPatrolTabName(self):
        return self.patrolTabName
    
    def set_callback(self, func):
        # """设置回调函数"""
        self.callback = func
    
    def setup_ui(self):
        self.create_menu()
        self.create_widgets()
        self.status_view()

    def create_menu(self):
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)

        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(label="打开", command=self.open_file)
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.root.quit)

        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="关于", command=self.about)

    def status_view(self):
        self.status = tk.Label(self.root, text="就绪", bd=1, relief=tk.SUNKEN, anchor=tk.W)
        self.status.pack(side=tk.BOTTOM, fill=tk.X)
    
    def create_widgets(self):

        main = tk.Frame(self.root)
        main.pack(fill="both", expand=True, padx=10, pady=10)
        
        self.widgetFileUi(main)
        self.widgetDateUi(main)
        self.widgetConfirmUi(main)
        self.widgetResultUi(main)
        # confirmFrame = tk.Frame(main, bg="red")
        # confirmFrame.pack(fill="both", expand=True)
        # tk.Button(self.confirmFrame, text="确定", command=self.confirmCallback).pack(side='left')
   
    def widgetFileUi(self,main):
        fileFrame = tk.Frame(main, height=50)
        fileFrame.pack(fill="x")
        tk.Label(fileFrame, text="选择文件分析文件：").pack(side='left')
        
        filePathInput = tk.Entry(fileFrame, textvariable=self.filePath,state='readonly')
        filePathInput.pack(side='left',padx=5,fill='x',expand=True)
        tk.Button(fileFrame, text="浏览", command=self.open_file).pack(side='left')

        fileTabFrame = tk.Frame(main, height=50)
        fileTabFrame.pack(fill="x",pady=5)
        tk.Label(fileTabFrame, text="分析表名").pack(side='left')
        mainNameInput = tk.Entry(fileTabFrame, textvariable=self.mainTabName)
        mainNameInput.pack(side='left',padx=5)
        
        fileTabOtherFrame = tk.Frame(main, height=50)
        fileTabOtherFrame.pack(fill="x",pady=5)
        tk.Label(fileTabOtherFrame, text="行政巡堂表名").pack(side='left')
        patrolNameInput = tk.Entry(fileTabOtherFrame, textvariable=self.patrolTabName)
        patrolNameInput.pack(side='left',padx=5)
        tk.Label(fileTabOtherFrame, text="特殊日子表名").pack(side='left',padx=5)
        dateNameInput = tk.Entry(fileTabOtherFrame, textvariable=self.dateTabName)
        dateNameInput.pack(side='left',padx=5)
        
        self.add_placeholder_to_entry(mainNameInput, self.placeholdeMain)
        self.add_placeholder_to_entry(patrolNameInput, self.placeholdePatrol)
        self.add_placeholder_to_entry(dateNameInput, self.placeholdeDate)

    def widgetDateUi(self,main):
        dateRadioFrame = tk.Frame(main,heigh=50)
        dateRadioFrame.pack(fill="x",pady=5)
        tk.Label(dateRadioFrame, text="日期：").pack(side='left')
        options = [("单月", "one"), ("自由", "more")]
        
        for lang, value in options:
            tk.Radiobutton(dateRadioFrame, text=lang, variable=self.dateTypeSelected, value=value).pack(side='left',padx=5)
        
        dateMainFrame = tk.Frame(main,height=50)
        dateMainFrame.pack(fill="x")

        self.dateRadioOneFrame = tk.Frame(dateMainFrame,heigh=50)
        self.dateRadioOneFrame.pack(fill="x")
        tk.Label(self.dateRadioOneFrame, text="选择月份：").pack(side='left')
        currentYear = datetime.now().year
        self.yearOneCombobox = ttk.Combobox(self.dateRadioOneFrame,  values=list(range(currentYear-10, currentYear+11)), width=8, state='readonly')
        self.yearOneCombobox.pack(side='left',padx=5)
        self.yearOneCombobox.set(currentYear)
          
        currentMonth = datetime.now().month
        self.monthOneCombobox = ttk.Combobox(self.dateRadioOneFrame,  values=[f"{i:02d}" for i in range(1, 13)], width=6, state='readonly')
        self.monthOneCombobox.pack(side='left',padx=5)
        self.monthOneCombobox.set(currentMonth)
        
        self.dateRadioMoreFrame = tk.Frame(dateMainFrame,heigh=50)
        self.dateRadioMoreFrame.pack(fill="x")
        tk.Label(self.dateRadioMoreFrame, text="开始时间：").pack(side='left')
        dateMoreStarInput = tk.Entry(self.dateRadioMoreFrame, textvariable=self.dateMoreStart)
        dateMoreStarInput.pack(side='left',padx=5)
        tk.Label(self.dateRadioMoreFrame, text="结束时间：").pack(side='left')
        dateMoreEndInput = tk.Entry(self.dateRadioMoreFrame, textvariable=self.dateMoreEnd)
        dateMoreEndInput.pack(side='left',padx=5)

         # 绑定变量变化
        self.dateTypeSelected.trace('w', self.updateDateType)
        self.updateDateType()
        self.add_placeholder_to_entry(dateMoreStarInput, self.placeholdeMoreStart)
        self.add_placeholder_to_entry(dateMoreEndInput, self.placeholdeMoreEnd)

    def widgetConfirmUi(self,main):
        confirmFrame = tk.Frame(main, height=50)
        confirmFrame.pack(fill="x", pady=10)
        confirmBtn = tk.Button(confirmFrame, text="确定", width=20, command=self.confirmCallback)
        confirmBtn.pack(expand=True)
        tk.Label(confirmFrame, text="统计结果:").pack(side='left')

    def widgetResultUi(self, main):
        resultFrame = tk.Frame(main, bg="red")
        resultFrame.pack(fill="both",expand=True)
        self.tree = ttk.Treeview(resultFrame,show=('headings'))
        
        h_scroll = ttk.Scrollbar(resultFrame, orient="horizontal", command=self.tree.xview)
        h_scroll.pack(side='bottom', fill='x')
        v_scroll = ttk.Scrollbar(resultFrame, orient="vertical", command=self.tree.yview)
        v_scroll.pack(side='right', fill='y')
        self.tree.configure(yscrollcommand=v_scroll.set, xscrollcommand=h_scroll.set)
        self.tree.pack(expand=True, fill=tk.BOTH)

    def setResultValue(self, resultData):
        # 设置列标题
        self.resultData = resultData.reset_index()
        self.resultData = self.resultData.fillna('').astype(str)
        self.resultData = self.resultData.replace('NaT', '')
        
        # self.resultData.columns.values[0]='星期'
        print(self.resultData)
        print(self.resultData.columns)
        
        # print(tabulate(self.resultData, headers='keys', tablefmt='psql', showindex=True))
        print("======= 更新表数据 =======")
        # 清空现有数据
        for item in self.tree.get_children():
           self.tree.delete(item)
        columns = self.resultData.columns.tolist()
        print(columns)
        self.tree.config(columns=columns)
        for col in self.resultData.columns:
            self.tree.heading(col, text=col)
            self.tree.column(col, width=20)  # 可以调整宽度
        # 添加数据到Treeview
        for index, row in self.resultData.iterrows():
            self.tree.insert("", tk.END, values=list(row))


    def confirmCallback(self):
        filePath = self.getFilePath().get()
        if self.isStrEmpty(filePath):
            messagebox.showinfo("错误提示", "文件路径不能为空！")
            return
        fileMainTableName = self.getFileTabMainName().get().strip()
        print(fileMainTableName)
        if self.isStrEmpty(fileMainTableName) or fileMainTableName == self.placeholdeMain:
            messagebox.showinfo("错误提示", "主表名不能为空！")
            return
        
        excelFile = pd.ExcelFile(filePath)
        allSheets = excelFile.sheet_names
        print(allSheets)
        if not fileMainTableName in allSheets:
            messagebox.showinfo("错误提示", "主表名不存在！")
            return

        fileDateTableName = self.getFileTabDateTabName().get().strip()
        print(fileDateTableName)
        if self.isStrNotEmpty(fileDateTableName) and fileDateTableName != self.placeholdeDate and not fileDateTableName in allSheets:
            messagebox.showinfo("错误提示", "特殊日子表不存在！")
            return
        
        if fileDateTableName == self.placeholdeDate:
            fileDateTableName = ''

        filePatrolTableName = self.getFileTabPatrolTabName().get().strip()
        if self.isStrNotEmpty(filePatrolTableName) and filePatrolTableName != self.placeholdePatrol and not filePatrolTableName in allSheets:
            messagebox.showinfo("错误提示", "行政巡堂表不存在！")
            return
        if filePatrolTableName == self.placeholdePatrol:
            filePatrolTableName = ''

        dateTypeSelected = self.dateTypeSelected.get()
        dateMoreStart = self.dateMoreStart.get().strip()
        dateMoreEnd = self.dateMoreEnd.get().strip()

        if dateTypeSelected == "more":
            if self.isStrEmpty(dateMoreStart) or dateMoreStart == self.placeholdeMoreStart:
                messagebox.showinfo("错误提示", "时间为空！")
                return
                
            if self.isStrEmpty(dateMoreEnd) or dateMoreEnd == self.placeholdeMoreEnd:
                messagebox.showinfo("错误提示", "时间为空！")
                return
            if not self.is_date(dateMoreStart) or not self.is_date(dateMoreEnd):
                messagebox.showinfo("错误提示", "时间格式错误，例：2025-01-01")
                return
            startTime = datetime.strptime(dateMoreStart,"%Y-%m-%d")
            endTime = datetime.strptime(dateMoreEnd,"%Y-%m-%d")
            if startTime > endTime:
                messagebox.showinfo("错误提示", "开始时间不能大于结束时间")
                return

        yearOne = int(self.yearOneCombobox.get())
        monthOne =int(self.monthOneCombobox.get())

        if self.callback:
            self.callback(filePath,
                        fileMainTableName,
                        fileDateTableName,
                        filePatrolTableName,
                        dateTypeSelected,
                        yearOne,
                        monthOne,
                        dateMoreStart,
                        dateMoreEnd)

    def isStrNotEmpty(self,strValue):
        return not self.isStrEmpty(strValue)
    
    def isStrEmpty(self,strValue):
        return isinstance(strValue, str) and not strValue.strip()
    
    def is_date(self, string, fuzzy=False):
        try:
            parser.parse(string, fuzzy=fuzzy)
            return True
        except (ValueError, TypeError):
            return False

    def updateDateType(self,*args):
        dateType = self.dateTypeSelected.get()
        print('updateDateType = '+ dateType)
        if dateType == "one":
            self.dateRadioMoreFrame.pack_forget()
            self.dateRadioOneFrame.pack(side='left',padx=5)
        else:
            self.dateRadioOneFrame.pack_forget()
            self.dateRadioMoreFrame.pack(side='left',padx=5)

      
   
    def analyze_data(self):
        # 这里调用你的数据处理逻辑
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, "正在分析...\n")
        # 示例
        self.result_text.insert(tk.END, "分析完成！共处理 100 条数据。\n")

    def about(self):
        messagebox.showinfo("关于", f"Excel统计小玩具\n版本 1.0\n© 1988-{datetime.now().year}")

    def open_file(self):
        file_path = filedialog.askopenfilename(
            title="选择文件",
            filetypes=[("Excel 文件", "*.xlsx"), ("所有文件", "*.*")]
        )
        if file_path:
            self.filePath.set(file_path)


    def add_placeholder_to_entry(self,entry, placeholder, color='grey'):
        """为 Entry 添加提示文案"""
        def on_focus_in(event):
            if entry.get() == placeholder:
                entry.delete(0, 'end')
                entry.config(foreground='black')  # 输入时文字颜色

        def on_focus_out(event):
            if entry.get() == '':
                entry.insert(0, placeholder)
                entry.config(foreground=color)

        # 初始设置
        entry.insert(0, placeholder)
        entry.config(foreground=color)
        
        # 绑定事件
        entry.bind("<FocusIn>", on_focus_in)
        entry.bind("<FocusOut>", on_focus_out)


# ========= 主程序入口 =========
if __name__ == "__main__":
    root = tk.Tk()
    app = MainUi(root)
    root.mainloop()